layui.define(['exbase', 'jquery', 'form', 'layer', 'ExTree'], function (exports) {
    "use strict";

    var $ = layui.$;
    var exbase = layui.exbase;
    var form = layui.form, $dom = $(document), $win = $(window);
    var SELECT_TREE_CLASS = "select-tree-tag"
    var SELECT_TREE_RENDERED_CLASS = "layui-form-select"
    var ELEM = '.layui-form';
    var tree = layui.tree;


    var multiSelect = function () {
    };
    multiSelect.prototype.init = function () {
        var ts = this;
        $('select[multiple]').each(function (idx, item) {
            var t = $(this),
                selected_vals = [],
                selds = [];
            t.find('option:selected').each(function () {
                selds.push($(this).val());
            })
            t.next().addClass('multi').find('.layui-select-title').click(function () {
                selected_vals && $(this).find('input').val(selected_vals.join(','));
            }).next().find('dd').each(function () {
                var dt = $(this),
                    checked = (dt.hasClass('layui-this') || $.inArray(dt.attr('lay-value'), selds) > -1) ? 'checked' : '',
                    title = dt.text(),
                    disabled = dt.attr('lay-value') === '' ? 'disabled' : '';
                dt.html('<input type="checkbox" lay-skin="primary" title="' + title + '" ' + checked + ' ' + disabled + '>');
                ts.selected(selected_vals, t, dt);
            }).click(function (e) {
                var dt = $(this);
                // 点击下拉框每一行触发选中和反选
                if (e.target.localName == 'dd' && dt.attr('lay-value') !== '') {
                    var status = dt.find('.layui-form-checkbox').toggleClass('layui-form-checked').hasClass('layui-form-checked');
                    dt.find('input').prop('checked', status);
                }
                // 禁止下拉框收回
                dt.parents('.layui-form-select').addClass('layui-form-selected');
                ts.selected(selected_vals, t, dt);
            });
        })
        form.render('checkbox');
    }

    multiSelect.prototype.selected = function (selected_vals, t, dt) {
        // 选中值存入数组
        selected_vals = [];
        // 先清除真实下拉款选中的值，在下面循环中重新赋值选中
        t.find('option').prop('selected', false);
        dt.parents('dl').find('[type=checkbox]:checked').each(function () {
            var val = $(this).parent().attr('lay-value');
            t.find('option[value=' + val + ']').prop('selected', true);
            selected_vals.push($(this).attr('title'));
        })
        // 显示已选信息
        dt.parents('dl').prev().find('input').val(selected_vals.join(','));
    }
    var multiSelect_instance = new multiSelect()
    multiSelect_instance.init()

    class ExForm {
        superRender = form.render
        render = function (type, filter, treeConfigs) {
            var that = this
                , elemForm = $(ELEM + function () {
                    return filter ? ('[lay-filter="' + filter + '"]') : '';
                }()),
                dictionarySelect = function (callback) {
                    var dtdArray = new Array()
                    elemForm.find('select[dict-url]').each(function (idx, item) {
                        var t = $(this);
                        var dtd = $.Deferred();
                        $.ajax({
                            url: t.attr("dict-url"),
                            method: 'GET',
                            success: function (data) {
                                if (data.code === exbase.AJAX_SUCCESS_CODE) {
                                    $.each(data.data, function (index, elem) {
                                        t.append(`<option value="${elem.code}" ${elem.defaultValue ? 'selected' : ''}>${elem.codeName}</option>`)
                                    })
                                    dtd.resolve()
                                } else {
                                    dtd.reject()
                                }
                            }
                        })
                        dtdArray.push(dtd)
                    })
                    $.when.apply(null, dtdArray).done(function () {
                        // layer.msg('加载动态Select成功', {icon: 0})
                        callback();
                    }).fail(function () {
                        layer.msg('加载动态Select失败', {icon: 2})
                    })
                }
                , items = {

                    selectTree: function () {
                        var TIPS = '请选择', CLASS = SELECT_TREE_RENDERED_CLASS
                            , TITLE = 'layui-select-title'
                            , NONE = 'layui-select-none'
                            , DISABLED = 'disabled'
                            , initValue = ''
                            , thatInput
                            , selects = elemForm.find('input.' + SELECT_TREE_CLASS + '[type=text]')
                            , hide = function (e, clear) {
                                if (!$(e.target).parent().hasClass(TITLE) || clear) {
                                    $('.' + CLASS).removeClass(CLASS + 'ed ' + CLASS + 'up');
                                }
                            }
                            //各种事件
                            , events = function (reElem, disabled, isSearch) {
                                var select = $(this)
                                    , title = reElem.find('.' + TITLE)
                                    , input = title.find('input')
                                    , dl = reElem.find('dl');

                                if (disabled) return;

                                //展开下拉
                                var showDown = function () {
                                        var top = reElem.offset().top + reElem.outerHeight() + 5 - $win.scrollTop()
                                            , dlHeight = dl.outerHeight();

                                        reElem.addClass(CLASS + 'ed');


                                        //上下定位识别
                                        if (top + dlHeight > $win.height() && top >= dlHeight) {
                                            reElem.addClass(CLASS + 'up');
                                        }
                                    }

                                    //隐藏下拉
                                    , hideDown = function (choose) {
                                        reElem.removeClass(CLASS + 'ed ' + CLASS + 'up');
                                        input.blur();
                                        if (choose) return;
                                    }

                                //点击标题区域
                                title.on('click', function (e) {
                                    reElem.hasClass(CLASS + 'ed') ? (
                                        hideDown()
                                    ) : (
                                        hide(e, true),
                                            showDown()
                                    );
                                });

                                //点击箭头获取焦点
                                title.find('.layui-edge').on('click', function () {
                                    input.focus();
                                });

                                //select 中 input 键盘事件
                                input.on('keyup', function (e) { //键盘松开
                                    var keyCode = e.keyCode;

                                    //Tab键展开
                                    if (keyCode === 9) {
                                        showDown();
                                    }
                                }).on('keydown', function (e) { //键盘按下
                                    var keyCode = e.keyCode;

                                    //Tab键隐藏
                                    if (keyCode === 9) {
                                        hideDown();
                                    }
                                });

                                $(document).off('click', hide).on('click', hide); //点击其它元素关闭 select
                            }


                        selects.each(function (index, select) {
                            var othis = $(this)
                                , name = othis.attr("name")
                                , required = select.hasAttribute('required')
                                , verify = othis.attr('lay-verify')
                                , hasRender = othis.next('.' + CLASS)
                                , disabled = this.disabled
                                , value = select.value
                                , treeLoader
                                , treeElemId = exbase.generateId('select-tree')
                                , isSearch = typeof othis.attr('lay-search') === 'string'
                                , placeholder = othis.attr('placeholder') || TIPS;
                            var treeConfig = Object.assign({}, treeConfigs[name], {
                                async: false,
                                url: othis.attr("url") || treeConfigs[name].url,
                                elem: "#" + treeElemId,
                                id: treeElemId,
                                showCheckbox: true,
                                oncheck: function (node) {
                                    var checks = treeLoader.getCheckedNode();
                                    var input = othis.next().find('input[type=text]')
                                    othis.val(checks.map(a => a.id).join(","))
                                    input.val(checks.map(a => a.title).join(","))
                                }
                            });

                            othis.hide();
                            othis.attr('name', '')

                            treeLoader = new layui.ExTree(treeConfig)
                            var reElem = $(['<div class="' + (isSearch ? '' : 'layui-unselect ') + CLASS
                                , (disabled ? ' layui-select-disabled' : '') + '">'
                                , '<div class="' + TITLE + '">'
                                , ('<input type="text" placeholder="' + placeholder + '" '
                                    + (required ? 'required' : '')
                                    + (verify ? 'lay-verify="' + verify + '"' : '')
                                    + ('value="' + (value || '') + '"') //默认值
                                    + ((!disabled && isSearch) ? '' : ' readonly') //是否开启搜索
                                    + ' class="layui-input'
                                    + (isSearch ? '' : ' layui-unselect')
                                    + (disabled ? (' ' + DISABLED) : '') + '">') //禁用状态
                                , '<i class="layui-edge"></i></div>'
                                , '<dl class="layui-anim layui-anim-upbit' + (othis.find('optgroup')[0] ? ' layui-select-group' : '') + '">'
                                , function () {
                                    var arr = [];
                                    arr.push(`<div id="${treeElemId}"></div>`)
                                    return arr.join("")
                                }(),
                                , '</dl>'
                                , '</div>'].join(''));
                            hasRender[0] && hasRender.remove(); //如果已经渲染，则Rerender
                            othis.after(reElem);
                            treeLoader.load();
                            othis.next().find("input[type=checkbox]").attr("name", name)
                            othis.next().find("input[type=checkbox]").attr('multiple', treeConfig.multiple)
                            events.call(this, reElem, disabled, isSearch);
                        })
                    }
                }
            dictionarySelect(function () {
                type ? (
                    items[type] ? items[type]() : hint.error('不支持的' + type + '表单渲染')
                ) : layui.each(items, function (index, item) {
                    item();
                });
                that.superRender(type, filter)
                multiSelect_instance.init()
            })
        }
    }

    form.verify({
        phone_null: [
            /^$|1\d{10}$/
            , '请输入正确的手机号'
        ],
        email_null: [
            /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/
            , '邮箱格式不正确'
        ]
        , url_null: [
            /^$|(^#)|(^http(s*):\/\/[^\s]+\.[^\s]+)/
            , '链接格式不正确'
        ]
        , number_null: function (value) {
            if (value === "") {
                return;
            }
            if (!value || isNaN(value)) return '只能填写数字'
        },
        username: function (value, item) { //value：表单的值、item：表单的DOM对象
            if (!new RegExp("^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$").test(value)) {
                return '用户名不能有特殊字符';
            }
            if (/(^\_)|(\__)|(\_+$)/.test(value)) {
                return '用户名首尾不能出现下划线\'_\'';
            }
            if (/^\d+\d+\d$/.test(value)) {
                return '用户名不能全为数字';
            }

            //如果不想自动弹出默认提示框，可以直接返回 true，这时你可以通过其他任意方式提示（v2.5.7 新增）
            if (value === 'xxx') {
                alert('用户名不能为敏感词');
                return true;
            }
        }

        //我们既支持上述函数式的方式，也支持下述数组的形式
        //数组的两个值分别代表：[正则匹配、匹配不符时的提示文字]
        , pass: [
            /^[\S]{6,12}$/
            , '密码必须6到12位，且不能出现空格'
        ]
    });

    exports('ExForm', new ExForm())
})